home *** CD-ROM | disk | FTP | other *** search
- /* -*- C -*-
- * LIBFUN.C
- *
- * (c)Copyright 1995 by Tobias Ferber, All Rights Reserved
- *
- * This file is part of ADOC.
- *
- * ADOC is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 1 of the License,
- * or (at your option) any later version.
- *
- * ADOC is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- /* $VER: $Id: libfun.c,v 1.7 1995/03/20 18:44:15 tf Exp $ */
-
- #include <ctype.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
-
- #include "libfun.h"
-
- /* strexpand.c */
- extern char *strexpand(char *, char **);
-
- /* minimum #of chars added to funsec.data with each realloc() */
- #define SECMINSIZE 1024
-
- /* list of sections in a function description */
-
- typedef struct funsec
- {
- struct funsec *succ, *pred;
- char *name; /* section title keyword */
- struct {
- char *text; /* section text */
- size_t len; /* strlen(text) */
- size_t size; /* #of chars allocated for text */
- } data;
-
- } funsec_t;
-
-
- /* library function nodes */
-
- typedef struct libfun
- {
- struct libfun *succ, *pred;
- char *name; /* name of the function: `library/function' */
- struct funsec *sec; /* list of sections in the function description */
-
- } libfun_t;
-
-
- /* variables */
-
- static libfun_t *funlist = (libfun_t *)0; /* list of all functions */
- static libfun_t *funstack = (libfun_t *)0; /* function on the stack */
- static libfun_t *thisfun = (libfun_t *)0; /* the current function (the one constructed last) */
- static funsec_t *thissec = (funsec_t *)0; /* the current section in the current function */
-
- char *pushfun(void) { char *result= funstack ? funstack->name : (char *)0; funstack = thisfun; return result; }
- char *popfun(void) { char *result= funstack ? funstack->name : (char *)0; thisfun = funstack; return result; }
-
- /**/
-
- static libfun_t *libfun_head(libfun_t *lf) { return (lf && lf->pred) ? libfun_head(lf->pred) : lf; }
- static libfun_t *libfun_tail(libfun_t *lf) { return (lf && lf->succ) ? libfun_tail(lf->succ) : lf; }
-
- static funsec_t *funsec_head(funsec_t *fs) { return (fs && fs->pred) ? funsec_head(fs->pred) : fs; }
- static funsec_t *funsec_tail(funsec_t *fs) { return (fs && fs->succ) ? funsec_tail(fs->succ) : fs; }
-
- /*
- ** NEWFUN
- */
-
- static libfun_t *libfun_new(char *fun)
- {
- libfun_t *lf= (libfun_t *)0;
-
- if(fun)
- {
- lf= (libfun_t *)malloc( sizeof(libfun_t) );
-
- if(lf)
- {
- lf->name= strdup(fun);
-
- if(lf->name)
- {
- lf->succ =
- lf->pred = (libfun_t *)0;
- lf->sec = (funsec_t *)0;
- }
- else
- {
- free(lf);
- lf= (libfun_t *)0;
- }
- }
- }
-
- return lf;
- }
-
- /**/
-
- int newfun(char *fun)
- {
- libfun_t *new= libfun_new(fun);
-
- if(new)
- {
- libfun_t *lf= libfun_tail(funlist);
-
- if(lf)
- {
- lf->succ= new;
- new->pred= lf;
- }
- else funlist= new;
- }
-
- thisfun= new;
- thissec= new->sec;
-
- return new ? 0:1;
- }
-
- /*
- ** FUNSORT
- */
-
- static int funbubble(libfun_t *a)
- {
- int result= 0;
-
- /* perform a recursive bubble-sort on `a' and it's successors
- return the #of bubbles */
-
- if(a && a->succ)
- {
- libfun_t *b= a->succ;
-
- if( strcmp(a->name, b->name) > 0 )
- {
- if( (b->pred= a->pred) )
- b->pred->succ= b;
-
- if( (a->succ= b->succ) )
- a->succ->pred= a;
-
- b->succ= a;
- a->pred= b;
-
- ++result;
- }
-
- result += funbubble(b);
- }
-
- return result;
- }
-
- /**/
-
- void funsort(void)
- {
- /* as long as there are bubbles... */
- while( funbubble(libfun_head(funlist)) );
-
- /* sorting might have made another libfun_t the head of funlist */
- funlist= libfun_head(funlist);
-
- for(thisfun= funlist; thisfun; thisfun= thisfun->succ)
- {
- /* make sure that thisfun->sec is the head of the sections */
- thisfun->sec= funsec_head(thisfun->sec);
- }
-
- thisfun= (libfun_t *)0;
- thissec= (funsec_t *)0;
- }
-
-
- /*
- ** FUNEXPAND
- */
-
- int funexpand(char **macros)
- {
- int err= 0;
-
- libfun_t *lf;
- funsec_t *fs;
-
- for(lf= libfun_head(funlist); lf && (err==0); lf= lf->succ)
- {
- for(fs= funsec_head(lf->sec); fs && (err==0); fs= fs->succ)
- {
- if( fs->data.text )
- {
- char *x= strexpand(fs->data.text, macros);
-
- if(x)
- {
- free(fs->data.text);
- fs->data.text= x;
- }
- else err= 1;
- }
- }
- }
-
- return err;
- }
-
-
- /*
- ** NEWSEC
- */
-
- static funsec_t *funsec_new(char *title)
- {
- funsec_t *fs= (funsec_t *)malloc( sizeof(funsec_t) );
-
- if(fs)
- {
- fs->name= (title) ? strdup(title) : (char *)0;
-
- if(title && !fs->name)
- {
- free(fs);
- fs= (funsec_t *)0;
- }
-
- else
- {
- fs->succ =
- fs->pred = (funsec_t *)0;
-
- fs->data.text = (char *)0;
- fs->data.len =
- fs->data.size = 0;
- }
- }
-
- return fs;
- }
-
-
- int newsec(char *title)
- {
- int err= 0;
-
- if(thisfun)
- {
- funsec_t *new= funsec_new(title);
-
- if(new)
- {
- funsec_t *fs= funsec_tail(thisfun->sec);
-
- if(fs)
- {
- fs->succ= new;
- new->pred= fs;
- }
- else thisfun->sec= new;
- }
- else err= 2;
-
- thissec= new;
- }
- else err= 1;
-
- return err;
- }
-
- /*
- ** ADDTEXT
- */
-
- int addtext(char *text)
- {
- int err= 0;
-
- if(thissec)
- {
- if(text)
- {
- /* get the minimum needed size of the text block */
- size_t len= thissec->data.len + 1 + strlen(text) + 1; /* '\n' + '\0' */
-
- /* see if we have enough room for '\n' and text */
- if(len >= thissec->data.size)
- {
- /* resize the text buffer to the needed size + SECMINSIZE chars */
- char *old= thissec->data.text;
- char *new= (char *)realloc(old, (SECMINSIZE + len) * sizeof(char) );
-
- if(new)
- {
- thissec->data.text = new;
- thissec->data.size = SECMINSIZE + len;
-
- if(!old)
- *new= '\0';
- }
- else /* !new */
- {
- free(thissec->data.text);
- thissec->data.text = (char *)0;
- thissec->data.len =
- thissec->data.size = 0;
- err= 1;
- }
- }
-
- /* append the new `text' portion to the section text */
- if(thissec->data.text)
- {
- if(*thissec->data.text)
- strcat(thissec->data.text,"\n");
-
- if(*text)
- strcat(thissec->data.text,text);
-
- thissec->data.len= strlen(thissec->data.text);
- }
-
- }
- /* else: no error */
- }
- else err= -1;
-
- return err;
- }
-
-
- /*
- ** GETxxx
- */
-
- char *getfun(char *name)
- {
- libfun_t *lf= (libfun_t *)0;
-
- if(name)
- {
- for(lf= libfun_head(funlist); (lf && strcmp(lf->name, name)); lf= lf->succ)
- ;
- }
- else lf= thisfun;
-
- return lf ? lf->name : (char *)0;
- }
-
-
-
-
- char *getsec(char *name)
- {
- funsec_t *fs= (funsec_t *)0;
-
- if(name)
- {
- if(thisfun)
- {
- for(fs= funsec_head(thisfun->sec); (fs && strcmp(fs->name, name)); fs= fs->succ)
- ;
- }
- }
- else fs= thissec;
-
- return fs ? fs->data.text : (char *)0;
- }
-
-
- /*
- ** STEPxxx
- */
-
-
- char *stepfun(int trigger)
- {
- char *result= (char *)0;
-
- if(trigger > 0)
- {
- for(; thisfun && (trigger > 0); trigger--)
- thisfun= thisfun->succ;
- }
- else if(trigger < 0)
- {
- for(; thisfun && (trigger < 0); trigger++)
- thisfun= thisfun->pred;
- }
- else /* trigger == 0 */
- thisfun= libfun_head(funlist);
-
- if(thisfun)
- {
- thissec= funsec_head(thisfun->sec);
- result= thisfun->name;
- }
- else thissec= (funsec_t *)0;
-
- return result;
- }
-
-
-
- char *stepsec(int trigger)
- {
- char *result= (char *)0;
-
- if(trigger > 0)
- {
- for(; thissec && (trigger > 0); trigger--)
- thissec= thissec->succ;
- }
- else if(trigger < 0)
- {
- for(; thissec && (trigger < 0); trigger++)
- thissec= thissec->pred;
- }
- else /* trigger == 0 */
- {
- if(thisfun)
- thissec= funsec_head(thisfun->sec);
-
- else
- thissec= (funsec_t *)0;
- }
-
- if(thissec)
- result= thissec->name;
-
- return result;
- }
-
-
- /*
- ** FREEFUN
- */
-
- static funsec_t *funsec_dispose(funsec_t *fs)
- {
- if(fs)
- {
- fs->succ= funsec_dispose(fs->succ);
-
- if(fs->name)
- free(fs->name);
-
- if(fs->data.text)
- free(fs->data.text);
- }
-
- return (funsec_t *)0;
- }
-
- static libfun_t *libfun_dispose(libfun_t *lf)
- {
- if(lf)
- {
- lf->succ= libfun_dispose(lf->succ);
-
- if(lf->name)
- free(lf->name);
-
- lf->sec= funsec_dispose( funsec_head(lf->sec) );
-
- free(lf);
- }
-
- return (libfun_t *)0;
- }
-
- void funfree(void)
- {
- funlist= thisfun= libfun_dispose( libfun_head(funlist) );
- thissec= (funsec_t *)0;
- }
-